
import pygame
import math
import random
import sys
import time
import asyncio
from typing import List
from pygame import gfxdraw
import configparser
import colorsys
import numpy as np

# 初始化随机种子
random.seed(int(time.time() * 1000))

class LuckyWheel:
    def __init__(self, items: List[str], probabilities: List[float]):
        # 移除 pygame.init() 调用
        self.width, self.height = 800, 800
        self.screen = None  # 初始化为 None，将在 run_async 中设置
        self.caption = "幸运大转盘"
        
        # 奖项配置（名称、概率、颜色）
        self._items = items
        self._probabilities = probabilities
        print("你设置的奖项：")
        print(items)
        print("你设置的概率：")
        print([f'{p:.5f}' for p in probabilities])
        self.colors = self._generate_contrast_colors(len(items))
        
        # 检查输入合法性
        if len(items) != len(probabilities):
            print("[ERROR] 奖品数和概率数不相等！")
            sys.exit(1)
        
        total_prob = sum(probabilities)
        if not math.isclose(total_prob, 1.0,abs_tol=1e-6):
            print("[ERROR] 概率加和不等于1！")
            print(total_prob)
            sys.exit(1)
        
        # 字体设置（延迟到实际使用时初始化）
        self.font_large = None
        self.font_small = None
        
        # 转盘参数
        self.center = (self.width // 2, self.height // 2)
        self.radius = 300
        self.angle = 0
        self.spinning = False
        self.result = None
        self.target_sector = None
        self.adjusted_angles = None

    def initialize_pygame(self):
        """初始化 pygame 和相关设置，并添加窗口大小调整功能"""
        pygame.init()
        # 设置初始窗口大小
        self.width, self.height = 800, 800
        self.screen = pygame.display.set_mode((self.width, self.height), pygame.RESIZABLE)
        pygame.display.set_caption(self.caption)

        # 字体设置
        self.font_large = pygame.font.SysFont('simhei', 30)
        self.font_small = pygame.font.SysFont('simhei', 20)

        # 绑定窗口大小变化事件
        pygame.display.set_mode((self.width, self.height), pygame.RESIZABLE)
        pygame.event.set_allowed([pygame.QUIT, pygame.VIDEORESIZE, pygame.KEYDOWN])

        self.adjusted_angles = self._adjust_angles(self.probabilities)

    def _adjust_angles(self, probs):
        """调整低概率扇区角度"""
        min_angle = 10  # 最小显示角度
        base_angles = [p * 360 for p in probs]
        
        # 标记需要调整的扇区（概率<0.01）
        adjust_indices = [i for i,p in enumerate(probs) if p < 0.01]
        other_indices = [i for i,p in enumerate(probs) if p >= 0.01]
        
        # 计算需要补偿的角度
        need_compensation = sum(min_angle - base_angles[i] for i in adjust_indices)
        total_other = sum(base_angles[i] for i in other_indices)
        
        # 按比例从其他扇区扣除角度
        adjusted = base_angles.copy()
        for i in adjust_indices:
            adjusted[i] = min_angle
        for i in other_indices:
            adjusted[i] -= (base_angles[i]/total_other) * need_compensation
        
        return adjusted

    def adjust_wheel_size(self, new_width, new_height):
        """根据新的窗口大小调整转盘大小"""
        self.width, self.height = new_width, new_height
        self.center = (self.width // 2, self.height // 2)
        # 这里可以根据需要调整转盘半径与窗口大小的比例
        self.radius = min(self.width, self.height) * 0.375  # 保持转盘相对大小不变

    @property
    def items(self):
        return self._items

    @property
    def probabilities(self):
        return self._probabilities


    def _generate_contrast_colors(self, num_colors):
        colors = []
        for i in range(num_colors):
            # 使用HSV色彩空间均匀分布色相
            hue = i / float(num_colors)
            # 固定较高的饱和度和亮度确保颜色足够鲜艳
            saturation = 0.7 + 0.2 * (i % 3)  # 添加一些变化
            value = 0.8 + 0.15 * (i % 2)      # 确保亮度足够
            
            # 转换为RGB
            rgb = colorsys.hsv_to_rgb(hue, saturation, value)
            # 转换为0-255范围并确保颜色足够亮
            r, g, b = [int(255 * max(0.6, x)) for x in rgb]
            colors.append((r, g, b))
        return colors

    def draw_wheel(self):
        """绘制优化后的转盘"""
        start_angle = 0
        for i, (item, angle, color) in enumerate(zip(self.items, self.adjusted_angles, self.colors)):
            end_angle = start_angle + angle
            
            # 高精度绘制扇形
            points = [self.center]
            step = 0.5  # 高精度步长
            for a in np.arange(start_angle, end_angle, step):
                x = self.center[0] + self.radius * math.cos(math.radians(a + self.angle))
                y = self.center[1] + self.radius * math.sin(math.radians(a + self.angle))
                points.append((x, y))
            gfxdraw.filled_polygon(self.screen, points, color)
            gfxdraw.aapolygon(self.screen, points, (0, 0, 0))
            
            # 文字绘制（自动调整大小）
            mid_angle = (start_angle + end_angle) / 2
            text_radius = self.radius * 0.7
            text_x = self.center[0] + text_radius * math.cos(math.radians(mid_angle + self.angle))
            text_y = self.center[1] + text_radius * math.sin(math.radians(mid_angle + self.angle))
            
            font = self.font_small if len(item) > 4 else self.font_large
            text = font.render(item, True, (0, 0, 0))
            text_rect = text.get_rect(center=(text_x, text_y))
            rotated_text = pygame.transform.rotate(text, -mid_angle - self.angle)
            rotated_rect = rotated_text.get_rect(center=text_rect.center)
            self.screen.blit(rotated_text, rotated_rect)
            
            start_angle = end_angle

        # 绘制指针
        pygame.draw.polygon(self.screen, (255, 0, 0), [
            (self.center[0] + 20, self.center[1] + self.radius + 40),
            (self.center[0], self.center[1] + self.radius),
            (self.center[0] - 20, self.center[1] + self.radius + 40)
        ])
        pygame.draw.circle(self.screen, (200, 0, 0), self.center, 15)

    def spin(self):
        """启动旋转"""
        if not self.spinning:
            self.spinning = True
            self.spin_time = 0
            self.spin_duration = random.uniform(3, 5)
            # 按预设概率选择目标区域
            # cumulative_probs = [0] + [sum(self.probabilities[:i + 1]) for i in range(len(self.probabilities))]
            cumulative_angles = [0] + [sum(self.adjusted_angles[:i + 1]) for i in range(len(self.adjusted_angles))]
            target_sector = random.choices(range(len(self.probabilities)), weights=self.probabilities)[0]

            # 修复索引越界问题
            # if target_sector == len(self.probabilities) - 1:
            #     self.target_end_angle = 360  # 最后一个区域结束角度为360度
            # else:
            self.target_end_angle = cumulative_angles[target_sector + 1]

            self.target_start_angle = cumulative_angles[target_sector]
            self.target_angle = (-random.uniform(self.target_start_angle, self.target_end_angle) + 90) % 360 + 360 * 5
            self.target_sector = target_sector

    def get_target_sector_instantly(self):
        target_sector = random.choices(range(len(self.probabilities)), weights=self.probabilities)[0]
        return target_sector

    def update(self, dt):
        """更新旋转动画"""
        if self.spinning:
            self.spin_time += dt
            if self.spin_time < self.spin_duration:
                progress = self.spin_time / self.spin_duration
                ease_progress = 1 - (1 - progress) ** 3
                self.angle = ease_progress * (self.target_angle) + 360 * 5
            else:
                self.spinning = False
                self.angle = self.target_angle % 360
                self.result = self.get_result()

    def get_result(self):
        """根据角度确定奖项"""
        angle = (-self.angle + 90) % 360
        cumulative = 0
        for i, prob in enumerate(self.adjusted_angles):
            cumulative += prob
            start_angle = cumulative - prob
            end_angle = cumulative

            if start_angle <= angle < end_angle:
                print(self.items[i])
                return self.items[i]
            
        return self.items[-1]

    async def run_async(self):
        """运行异步主循环，并初始化 pygame"""
        self.initialize_pygame()  # 在这里初始化 pygame
        
        clock = pygame.time.Clock()
        running = True
        
        while running:
            dt = clock.tick(60) / 1000.0
            
            for event in pygame.event.get():
                if event.type == pygame.QUIT:
                    running = False
                elif event.type == pygame.VIDEORESIZE:
                    # 获取新的窗口大小
                    new_size = event.size
                    self.adjust_wheel_size(new_size[0], new_size[1])
                    # 重新设置屏幕大小
                    self.screen = pygame.display.set_mode(new_size, pygame.RESIZABLE)
                elif event.type == pygame.KEYDOWN:
                    if event.key == pygame.K_SPACE:
                        self.spin()
            
            self.update(dt)
            
            self.screen.fill((255, 255, 255))
            self.draw_wheel()
            
            if self.result and not self.spinning:
                text = self.font_large.render(f"恭喜获得: {self.result}", True, (0, 0, 0))
                self.screen.blit(text, (self.width // 2 - 100, 50))
            
            prompt = self.font_small.render("按空格键开始抽奖", True, (100, 100, 100))
            self.screen.blit(prompt, (self.width // 2 - 80, self.height - 50))
            
            pygame.display.flip()
            
            await asyncio.sleep(0)  # 异步让步，允许其他任务运行
        
        pygame.quit()
        sys.exit()

# 假设LuckyWheel类和其他相关代码已经定义（如原文件中所示）

async def simulate_draws(num_draws: int, game: LuckyWheel):
    results = []
    for _ in range(num_draws):
        result = game.get_target_sector_instantly()  # 获取结果
        results.append(result)
        print(f"抽奖结果: {game.items[result]}")  # 输出结果到控制台
    for i in range(len(game.items)):
        print(f"奖项{game.items[i]}出现次数为{results.count(i)}")

    return results

# 示例使用
async def main():
    # 读取配置文件
    config = configparser.ConfigParser()
    config.read('config.ini')
    
    items = config['PRIZES']['items'].split(',')
    probabilities = [float(prob) for prob in config['PRIZES']['probabilities'].split(',')]
    
    game = LuckyWheel(items, probabilities)
    
    # 命令行交互选择批量抽取还是转盘抽取
    print("请选择抽奖模式:")
    print("1. 批量抽取")
    print("2. 转盘抽取")
    
    choice = input("输入选项(1/2): ")
    
    if choice == '1':
        try:
            while True:
                num_draws = int(input("请输入批量抽取的次数: "))
                await simulate_draws(num_draws, game)
        finally:
            sys.exit(1)
    elif choice == '2':
        await game.run_async()
    else:
        print("无效选项，程序退出。")
        sys.exit(1)

# 运行异步主函数
if __name__ == "__main__":
    import multiprocessing
    multiprocessing.freeze_support()
    asyncio.run(main())